package satir.cell;

import org.json.*;
import satir.framework.*;
import satir.framework.JSONIOPerformer.*;

/**
 * The Class Board.
 * 
 * @version 2.0 March 2012
 * @author Chris Chan
 */
public class Board {

	/** The width(number of cell) of board. */
	private int width;
	/** The height(number of cell) of board. */
	private int height;
	/** Number of cell for walking. */
	private int numOfRoad;
	/** Storing the array of cell for walking */
	private Cell[] cellRoadArray;
	/** The cell array for displaying cells in the board. */
	private Cell[][] cellArrayForDisplay;
	/** The head cell. */
	private Cell head;
	/** The tail cell. */
	private Cell tail;

	/**
	 * Instantiates a new board. It will read the Board.config to retrieve
	 * required information And create cell according to the configure file
	 * 
	 */
	public Board() {
		try {
			// Use JSONIOPerformer to get the Board.config
			JSONIOPerformer boardConfig = new JSONIOPerformer("Board.config");
			// Retrieve the JSONObject and get required data
			this.width = boardConfig.retrieve().getInt("Width");
			this.height = boardConfig.retrieve().getInt("Height");
			// Calculate the number of road
			this.numOfRoad = 2 * (width + height) - 4;
			cellArrayForDisplay = new Cell[width][height];
			cellRoadArray = new Cell[numOfRoad];
			JSONArray cellTypes = boardConfig.retrieve().getJSONArray(
					"CellType");
			// Create cell according to the boardCofig specified cell type
			for (int i = 0; i < cellTypes.length(); i++) {
				Cell cell = LazyInitiator.getCell(cellTypes.getString(i), true);
				addToTail(cell);
				cellRoadArray[i] = cell;
			}
		} catch (JSONIOPerformerReadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONIOPerformerJSONDecodeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Put the created cell into array for display
		int leftSideCnt = numOfRoad - 1;
		int rightSideCnt = width;
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				if (i == 0) { // First row
					cellArrayForDisplay[i][j] = cellRoadArray[j];
				} else if (i == height - 1) { // Last Row
					cellArrayForDisplay[i][j] = cellRoadArray[leftSideCnt--];
				} else if (i < height) { // Middle Row
					if (j == 0) { // Rightmost Column
						cellArrayForDisplay[i][j] = cellRoadArray[leftSideCnt--];
					} else if (j == width - 1) { // Leftmost Column
						cellArrayForDisplay[i][j] = cellRoadArray[rightSideCnt++];
					} else { // Center
						cellArrayForDisplay[i][j] = LazyInitiator.getCell("SpaceCell", false);
					}
				}
			}
		}
	}

	/**
	 * Show board.
	 */
	public void showBoard() {
		int rowNum = 0;
		int cellHeight = cellArrayForDisplay[0][0].getHeight();
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < cellHeight; j++) {
				for (int k = 0; k < width; k++) {
					cellArrayForDisplay[i][k].display(rowNum);
				}
				rowNum++;
				System.out.println("");
			}
			rowNum = 0;
			System.out.println("");
		}
	}

	/**
	 * Adds cell the to head.
	 * 
	 * @param cell the cell that will be added to head
	 */
	private void addToHead(Cell cell) {
		if (head == null) {
			head = tail = cell;
		} else {
			cell.setNextCell(head);
			head = cell;
		}
	}

	/**
	 * Adds cell the to tail.
	 * 
	 * @param cell the cell that will be added to tail
	 */
	private void addToTail(Cell cell) {
		if (tail == null) {
			head = tail = cell;
		} else {
			tail.setNextCell(cell);
			tail = cell;
			cell.setNextCell(head);
		}
	}

	/**
	 * Gets the head.
	 * 
	 * @return the head cell
	 */
	public Cell getHead() {
		return this.head;
	}
}